package com.force.module.mcpclient.service;

import cn.hutool.cache.Cache;
import cn.hutool.cache.impl.TimedCache;
import com.force.module.mcpclient.model.AliModel;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor;
import org.springframework.ai.chat.client.advisor.SafeGuardAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.InMemoryChatMemory;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class AliClientService {
    private final ChatMemory chatMemory = new InMemoryChatMemory();

    @Autowired(required = false)
    ChatClient.Builder chatClientBuilder;

    @Resource
    private EmbeddingModel embeddingModel;

    @Resource
    private ToolCallbackProvider toolCallbackProvider;


    // 定义一个缓存实例，比如 TimedCache，默认缓存时间 5 分钟
    private final Cache<String, ToolCallback[]> cache = new TimedCache<>(300_000); // 毫秒

    public ToolCallback[] getTools() {
        String key = "tools";
        ToolCallback[] result = cache.get(key);

        if (result == null) {
            result = (ToolCallback[]) toolCallbackProvider.getToolCallbacks();
            cache.put(key, result);
        }

        return result;
    }

    public ChatClient getClient() {
        SimpleVectorStore build = SimpleVectorStore.builder(embeddingModel).build();
        return chatClientBuilder
                // 它定义了聊天机器人在回答问题时应当遵循的风格和角色定位。
                // .defaultSystem("以专业天气预报主持人的风格回答问题。")
                // 指定聊天客户端可用的工具
                .defaultAdvisors(
                        // 这里可以添加多个顾问 order(优先级)越小，越先执行
                        // 注意：顾问添加到链中的顺序至关重要，因为它决定了其执行的顺序。每个顾问都会以某种方式修改提示或上下文，一个顾问所做的更改会传递给链中的下一个顾问。
                        // 在此配置中，将首先执行MessageChatMemoryAdvisor，将对话历史记录添加到提示中。然后，问答顾问将根据用户的问题和添加的对话历史进行搜索，从而可能提供更相关的结果。
                        new MessageChatMemoryAdvisor(chatMemory, "chat-memory-advisor", 10),
                        // QuestionAnswerAdvisor 此顾问使用矢量存储提供问答功能，实现RAG（检索增强生成）模式
                        QuestionAnswerAdvisor.builder(build).userTextAdvise("""
                                下文信息如下，由 --------------------- 包围。

                                ---------------------
                                {question_answer_context}
                                ---------------------

                                根据给定的上下文以及提供的历史信息来回复用户的评论，而且要依据先前的知识。如果答案不在上下文中，优先搜索知识库，其次联网搜索，要告知用户你能提供的最好的答案。
                                """).order(1).build(),
                        // SafeGuardAdvisor是一个安全防护顾问，它确保生成的内容符合道德和法律标准。
                        SafeGuardAdvisor.builder().sensitiveWords(List.of("暴力")) // 敏感词列表
                                .order(2) // 设置优先级
                                .failureResponse("抱歉，我无法回答这个问题。").build(), // 敏感词过滤失败时的响应
                        // SimpleLoggerAdvisor是一个记录ChatClient的请求和响应数据的顾问。这对于调试和监控您的AI交互非常有用，建议将其添加到链的末尾。
                        new SimpleLoggerAdvisor()
                )
                .defaultOptions(AliModel.getModel())
                .build();
    }
}
